package com.hcm.kernel.sql;

import com.hcm.kernel.util.SystemConfig;
import com.hcm.kernel.xml.IgnoreDTDEntityResolver;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.Element;
import org.dom4j.io.SAXReader;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 从配置文件中加载sql，配置文件的路径可以在system.properties中配置
 */
public class CustomSQLUtil {
    private static Logger _log = LoggerFactory.getLogger(CustomSQLUtil.class);

    private static Map<String, String> _sqlMap = new HashMap<String, String>();

    static {
        String custom_sql = SystemConfig.getString("custom.sql.file");

        SAXReader reader = new SAXReader();
        reader.setValidation(false);
        reader.setEntityResolver(new IgnoreDTDEntityResolver());

        _sqlMap = parseSqlXml(reader, CustomSQLUtil.class.getResourceAsStream(custom_sql));
    }

    public static String get(String id) {
        String sql = _sqlMap.get(id);
        //if (PropUtil.getBoolean("custom.show.sql")) LogUtil.print(_log,sql);
        return sql;
    }

    private static Map<String, String> parseSqlXml(SAXReader reader, InputStream is) {
        Map<String, String> sqlMap = new HashMap<String, String>();
        try {
            Document document = reader.read(is);
            @SuppressWarnings("unchecked")
            List<Element> sqlList = document.getRootElement().elements();
            //这样可以得到所有custom-sql的子节点，所以限制sql中不可能再子节点，只能有一级

            for (Element child : sqlList) {
                //如果子节点为include，那么要进行再次解析
                if (child.getName().equalsIgnoreCase("include")) {
                    String sqlFile = child.attributeValue("file");
                    InputStream isx = CustomSQLUtil.class.getResourceAsStream(sqlFile);
                    if (isx == null) continue;
                    sqlMap.putAll(parseSqlXml(reader, isx));
                } else {
                    sqlMap.put(child.attributeValue("id"), child.getText());
                }
            }

        } catch (DocumentException e) {
            throw new RuntimeException("E0002:" + e.getMessage());//
        }
        return sqlMap;
    }
}
